package javango.forms.widgets;

import java.util.Map;

import javango.forms.fields.ChoiceField;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class SelectWidget<K,V> extends AbstractChoicesWidget<K,V> {

	private final static Log log = LogFactory.getLog(SelectWidget.class);

	public SelectWidget() {
		super(null);
	}

	public SelectWidget(Map<String, Object> attrs) {
		super(attrs);
	}
	
	public SelectWidget(Map<String, Object> attrs, Map<K,V> choices) {
		super(attrs);
		setChoices(choices);
	}
	
	@Override
	public String asText(Object value) {
		if (value == null) return ""; // TODO ddn rethink null handling,  probably should move this to the choice map...
		// but what about the isaddblankentry options here????
		
		Object choiceValue = this.getChoices().get(value); // pass the object,  or the toString??		
		return choiceValue == null ? "" : choiceValue.toString();
	}

	/**
	 *  coerce the provided value to the correct class type,  default implementation uses ConvertUtils.convert
	 * 
	 * @param value
	 * @param clazz
	 * @return
	 */
	protected Object coerce(Object value, Class clazz) {
		return ConvertUtils.convert(value, clazz);
	}
	public String render(String name, Object value, Map<String, Object> attrs) {
		Map<String, Object> finalAttrs = buildAttrs(attrs);
		finalAttrs.put("name", name);

		if (finalAttrs.containsKey("id")) {
			finalAttrs.put("id", String.format((String) finalAttrs.get("id"),
					name));
		}
		if (finalAttrs.containsKey("readonly")) {
			finalAttrs.remove("readonly");
			finalAttrs.put("disabled", "disabled");
		}

		StringBuilder b = new StringBuilder("<select");
		Util.flatatt(finalAttrs, b);
		b.append(">");
		
		value = value == null ? null : value instanceof String[] ? ((String[])value)[0] : value;

		String optionHtml = "<option value=\"%s\" %s>%s</option>"; // value, selected, display

		// TODO while setting allownull=true this works great for putting -- and still forcing the user to select it may not be intuitave
		// heck this should alwasy be prepended to the list if nothing is marked as selected!!
		if (isAddBlankEntry()) {
			b.append(String.format(optionHtml, "", "", "--"));
		}

		for (Map.Entry<K,V> entry : getChoices().entrySet()) {
			Object optionValue = value == null ? entry.getKey() : coerce(entry.getKey(), value.getClass());
			String selected = value == null ? "" : value.equals(optionValue) ? "selected=\"selected\"" : "";
			log.debug("optionValue : '" + optionValue + "'; value : '" + value + "'");
			b.append(String.format(optionHtml, formatKey(optionValue), selected, formatValue(entry.getValue())));
		}
		b.append("</select>");
		return b.toString();
	}

}
